package com.xlh.util;

import cn.hutool.core.io.FileUtil;
import com.xlh.enums.LocalResourcesEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 使用 pandoc 程序进行文档转换的工具类,需要 pandoc (安装过程见文档)
 *
 * @author zhr 2019/11/13
 */
public class PandocFileUtil {

    private static Logger logger = LoggerFactory.getLogger(PandocFileUtil.class);

    private static final String EXTRACT_MEDIA_PATH = LocalResourcesEnum.MARKDOWN_PICTURE.getLocalUploadPath();
    //    private static final String EXTRACT_MEDIA_PATH = "F:/";
    private static final String PROXY_MEDIA_PATH = LocalResourcesEnum.MARKDOWN_PICTURE.getProxyPath();

    private static final String CMD_DOCX_GFM = "pandoc %s -f docx+empty_paragraphs --wrap none --extract-media %s -t gfm";

    /**
     * 将docx文档转化为gfm文档,使用时,将待转换的docx文档绝对路径传入即可
     * gfm文档:github内核版本markdown文件
     */
    public static String docx2gfm(String docxPath) throws Exception {
        // 验证文件是否为docx文件,当前pandoc不支持doc的转换
        if (!isDocx(docxPath)) {
            throw new Exception("请上传07版本以上word文档");
        }

        String cmd = String.format(CMD_DOCX_GFM, docxPath, EXTRACT_MEDIA_PATH);

        // 执行文档转换命令
        Process process = Runtime.getRuntime().exec(cmd);

        // 静态文件映射,用于将image**文件名转换为随机的uuid
        Map<String, String> nameMap = new HashMap<>();

        // 解析并处理命令结果
        BufferedInputStream bis = new BufferedInputStream(process.getInputStream());

        BufferedReader br = new BufferedReader(new InputStreamReader(bis));
        StringBuffer buffer = new StringBuffer();
        String line;

        while ((line = br.readLine()) != null) {
            String lineTransform = transformImageName(nameMap, line);
            lineTransform = deleteCite(lineTransform);

            buffer.append(lineTransform).append("\n");
        }

        // 修改静态文件名称
        nameMap.forEach((name, newName) -> {
            File file = new File(EXTRACT_MEDIA_PATH + "/media/" + name);
            file.renameTo(new File(EXTRACT_MEDIA_PATH + "/media/" + newName));
        });

        bis.close();
        br.close();

        process.waitFor();
        if (process.exitValue() != 0) {
            bis = new BufferedInputStream(process.getErrorStream());
            br = new BufferedReader(new InputStreamReader(bis));

            throw new IOException(br.readLine());
        }

        process.destroy();

        return buffer.toString();
    }

    /**
     * 删除文本中的引用
     *
     * @param words 待处理文本片段
     * @return
     */
    private static String deleteCite(String words) {
        if (StringUtils.isNotBlank(words) && words.startsWith("> ")) {
            words = words.replaceFirst("> ", "");
        }

        return words;
    }

    private static boolean isDocx(String docxPath) {
        String extension = docxPath.substring(docxPath.lastIndexOf("."));
        return Objects.equals(extension, ".docx");
    }

    private static String transformImageName(Map<String, String> nameMap, String line) {
        String result = line;
        String regex = "image([\\w\\W]{0,3})(.png|.jpg|.jpeg|.gif|.tif|.tmp)";
        Pattern pattern = Pattern.compile(regex);
        Matcher m = pattern.matcher(line);

        // 识别为本行存在图片时执行此代码
        while (m.find()) {
            String imageName = m.group();
            // 找到图片映射,则直接替换;否则将新图片名称加入到映射中
            if (nameMap.get(imageName) == null) {
                String randomName = UUID.randomUUID().toString();
                String extension = imageName.substring(imageName.lastIndexOf("."));
                String newName = randomName + extension;

                result = result.replace(imageName, newName);
                nameMap.put(imageName, newName);
            } else {
                String newName = nameMap.get(imageName);

                result = result.replace(imageName, newName);
            }
        }

        // 替换文件路径为跨域代理路径
        result = result.replaceAll(EXTRACT_MEDIA_PATH, PROXY_MEDIA_PATH);

        return result;
    }

    public static void main(String[] args) throws Exception {
        String filePath = "C:\\Users\\962213579\\Desktop\\HDFSAPI操作-实验手册.docx";
//        String filePath = "C:\\Users\\962213579\\Desktop\\test.docx";

        String content = docx2gfm(filePath);

        System.out.println(content);

        String result = "C:\\Users\\962213579\\Desktop\\result2.md";

        // 在文件绝对地址创建文件
        FileUtil.file(result);
        // 向文件中编辑内容
        FileUtil.writeUtf8String(content, result);
    }
}
